﻿using System;
using System.Configuration;
using System.Data;
using System.Data.Common;
using JTLeigh.Commerce.Spencer.Core.Common;
using JTLeigh.Commerce.Spencer.Core.Common.Services;
using JTLeigh.Commerce.Spencer.Core.Data.Exceptions;
using Microsoft.Practices.EnterpriseLibrary.Data;
using Microsoft.Practices.Unity;

namespace JTLeigh.Commerce.Spencer.Core.Data.Services
{

	/// <summary>
	/// An <see cref="IDatabaseConnectionFactory"/> implementation that uses Enterprise Library's
	/// data access application block to create connections to databases.
	/// </summary>
	public sealed class DatabaseConnectionFactory : IDatabaseConnectionFactory
	{

		#region Properties

		/// <summary>
		/// Gets or sets the logging service to use to log events.
		/// </summary>
		[Dependency]
		public ILoggingService LoggingService { get; set; }

		/// <summary>
		/// Gets or sets the exception handling service to use to handle exceptions.
		/// </summary>
		/// <value>An <see cref="IExceptionHandlingService"/> implementation.</value>
		[Dependency]
		public IExceptionHandlingService ExceptionHandlingService { get; set; }

		#endregion // Properties

		#region IDatabaseConnectionFactory Members

		/// <summary>
		/// Creates a connection to the database with the specified database key.
		/// </summary>
		/// <param name="tenantId">The tenant identifier <see cref="Guid"/> of the tenant who the
		/// database connection is being created for.</param>
		/// <param name="databaseKey">The database key <see cref="String"/> used to identify the 
		/// database to connect to.</param>
		/// <returns>An <see cref="IDbConnection"/> connection to the specified database.</returns>
		public IDbConnection CreateDatabaseConnection(Guid tenantId, string databaseKey)
		{
            Database database;
            DbConnection connection;

            Safety.AssertArgumentNotNull("databaseKey", databaseKey);

			try
			{
				database = DatabaseFactory.CreateDatabase(databaseKey);
				connection = database.CreateConnection();
				return connection;
			}
			catch (ConfigurationErrorsException e)
			{
				LoggingService.Log(tenantId, CommonLogEntry.MissingInvalidDatabaseConnectionString(tenantId, databaseKey, e));
				throw;
			}
			catch (Exception e)
			{
				Exception te;

				te = DatabaseExceptionTransformer.Transform(e);
                if (te is DatabaseExceptionBase)
                {
                    throw te;
                }
                else
                {
                    throw;
                }
			}
		}

		#endregion // IDatabaseConnectionFactory Members

	}

}
